package com.sefonsoft.dataanalysis.service.impl;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.sefonsoft.dataanalysis.annotation.FieldMeta;
import com.sefonsoft.dataanalysis.annotation.Id;
import com.sefonsoft.dataanalysis.annotation.Table;
import com.sefonsoft.dataanalysis.dao.CollectinfoMapper;
import com.sefonsoft.dataanalysis.dao.CommonMapper;
import com.sefonsoft.dataanalysis.model.Collectinfo;
import com.sefonsoft.dataanalysis.service.CommonService;
import com.sefonsoft.dataanalysis.service.DataAnalysisSevice;
import com.sefonsoft.dataanalysis.service.model.Datas;
import com.sefonsoft.dataanalysis.utils.FieldUtils;
import com.sefonsoft.dataanalysis.utils.FileUtils;
import com.sefonsoft.dataanalysis.utils.PropertiesUtils;
import com.sefonsoft.dataanalysis.utils.Tools;

/**
 * 基础服务类
 * @author xgj
 *
 */
@Service
public abstract class BaseService<T> implements CommonService<T>,DataAnalysisSevice<T> {
	@Autowired
	private CollectinfoMapper collectinfoMapper;
	
	/**
	 * 数据源类型
	 *
	 */
	public static enum Type {
		JSON,HTML;
	}
	/**
	 * 查询常量
	 */
	private static final String 
			TABLE_NAME_STR = "tableName", 
			CONDITIONS = "conditions",
			GROUP = "group", 
			ORDER = "order", 
	 		LIMIT = "limit";
	
	/**
	 * 查询参数
	 */
	private static final Map<String, Object> QUERY_PARAMS = new HashMap<String, Object>(){
		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;

		{
			put(TABLE_NAME_STR,"collectinfo");//表名不呢过为空 如test_t
			put(CONDITIONS,"");//条件  如 1=1 and 2=2
			put(GROUP,"");//分组 如 group by id
			put(ORDER,"");//排序 如 order by id
			put(LIMIT,"");//分页默认10条 如 limit 0,10
		}
	};
	
	@Autowired
	private CommonMapper commonMapper;
	
	public int createTmpTable(boolean b) {
		String TABLE_DESC = getTClass().getAnnotation(Table.class).desc();
		String TABLE_NAME = getTClass().getAnnotation(Table.class).name();
		Field[] FIELDS = getTClass().getDeclaredFields(); 
		String _ID = getTClass().getAnnotation(Id.class).name();
		 StringBuffer sb = new StringBuffer("create table ");
		 sb.append(TABLE_NAME+"(");
         sb.append(_ID + " varchar(32) not null primary key,");
		 int num = 0;
		 for (Field field : FIELDS) {
			 FieldMeta fm =  field.getAnnotation(FieldMeta.class); 
			 num++;
			 if(Tools.isNull(fm)) {
				 if (num == FIELDS.length) {
					 sb.append(") ");
				 }
				 continue;
			 }
			 sb.append("`"+field.getName() +"` "+ fm.type());
			 if (fm.length()>0) {
				 sb.append("("+fm.length()+") ");
			 }
			 if (Tools.isNotNull(fm.name())) {
				 sb.append(" COMMENT '"+ fm.name() +"'");
			 }
			 if (num == FIELDS.length) {
				 sb.append(") ");
			 } else {
				 sb.append(",");
			 }
		 }
		 sb.append(" COMMENT '" + TABLE_DESC + "'");
		 sb.append(" DEFAULT CHARSET=utf8");
		 System.out.println(sb.toString());
		 int i = commonMapper.existTable(TABLE_NAME);
		 if (i == 0) {
			 commonMapper.createTmpTable(sb.toString());
		 } else if (b){
			 commonMapper.dropTable(TABLE_NAME);
			 commonMapper.createTmpTable(sb.toString());
		 }
		 
		return 0;
	}
	
	public int insert(List<T> ts) {
		if (ts == null || ts.isEmpty()) {
			return -1;
		}
		String TABLE_NAME = getTClass().getAnnotation(Table.class).name();
		String SYSID = getTClass().getAnnotation(Table.class).sysId();
		String FILEKIND = getTClass().getAnnotation(Table.class).fileKind();
		Field[] FIELDS = getTClass().getDeclaredFields(); 
		StringBuffer sb = new StringBuffer("INSERT INTO " + TABLE_NAME+"(");
		int num = 0;
		System.out.println(FIELDS.length);
		for (Field field : FIELDS) {
			sb.append("`"+field.getName()+"`");
			num++;
			System.out.println(num);
		    if (num == FIELDS.length) {
			   sb.append(") ");
		    } else {
			   sb.append(",");
		    }
		}
		num = 0;
		sb.append(" VALUES ");
		for (T t : ts) {
			List<String> list = FieldUtils.getFieldValueByName(FIELDS, t);
			sb.append("(");
			sb.append(StringUtils.join(list, ','));
			sb.append(" )");
			num++;
		    if (num != ts.size()) {
			   sb.append(",");
		    }
		}
		System.out.println(sb.toString());
		commonMapper.insert(sb.toString());
		collectinfoMapper.updateFlagBySysidAndFilekind(new Collectinfo(SYSID, FILEKIND));
		return 0;
	}

	static volatile int i = 0;
	
	public List<T> getDatasByHtml() throws IOException {
	    String SYSID = getTClass().getAnnotation(Table.class).sysId();
		String FILEKIND = getTClass().getAnnotation(Table.class).fileKind();
		List<Collectinfo> list = queryByCondition(SYSID,FILEKIND);
		List<T> resList = new ArrayList<>();
		//线程池处理 提高解析效率
	    ExecutorService exec = Executors.newFixedThreadPool(10); 
        ArrayList<Future<Datas<T>>>  results = new ArrayList<Future<Datas<T>>>();  
		final String path = PropertiesUtils.getKeyValue("data.address");
		for (Collectinfo collectinfo : list) {
		   results.add(exec.submit(new Callable<Datas<T>>(){
				@Override
				public Datas<T> call() throws Exception {
					String filePath = collectinfo.getFilepath();
					File input = new File(path + File.separator + filePath);
					Document doc = Jsoup.parse(input, "UTF-8", "");
					return dataAnalysisByHtml(doc);
				}
            }));  
		}
		for(Future<Datas<T>> fs : results){  
            try{  
            	if (fs.get() != null) {
            		resList.addAll(fs.get().getDatas());
            	}
            }catch(Exception e){  
                e.printStackTrace();  
            }finally{  
                exec.shutdown();  
            }  
        }  
		return resList;
	}

	
	@Override
	public List<T> getDatasByJSON() throws IOException {
		 String SYSID = getTClass().getAnnotation(Table.class).sysId();
		String FILEKIND = getTClass().getAnnotation(Table.class).fileKind();
		List<Collectinfo> list = queryByCondition(SYSID,FILEKIND);
		List<T> resList = new ArrayList<>();
		//线程池处理 提高解析效率
	    ExecutorService exec = Executors.newFixedThreadPool(5); 
        ArrayList<Future<Datas<T>>>  results = new ArrayList<Future<Datas<T>>>();  
		final String path = PropertiesUtils.getKeyValue("data.address");
		for (Collectinfo collectinfo : list) {
		   results.add(exec.submit(new Callable<Datas<T>>(){
				@Override
				public Datas<T> call() throws Exception {
					String filePath = collectinfo.getFilepath();
					String jsonStr = FileUtils.readToString(path + File.separator + filePath);
					return dataAnalysisByJson(jsonStr);
				}
            }));  
		}
		for(Future<Datas<T>> fs : results){  
            try{  
            	if (fs.get() != null) {
            		resList.addAll(fs.get().getDatas());
            	}
            }catch(Exception e){  
                e.printStackTrace();  
            }finally{  
                exec.shutdown();  
            }  
        }  
		return resList;
	}

	/**
	 * 获取映射关系
	 * @param sysid
	 * @param filekind
	 * @return
	 */
	protected List<Collectinfo> queryByCondition(String sysid, String filekind) {
		return collectinfoMapper.queryByCondition(sysid, filekind);
	}
	
	/**
	 * 查询数据
	 * 优先级传入参数第一优先  默认值第二优先
	 */
	public List<Map<String, Object>> query(String conditions, 
			String group, String order, String limit) {
		String TABLE_NAME = getTClass().getAnnotation(Table.class).name();
		QUERY_PARAMS.put(TABLE_NAME_STR, TABLE_NAME);
		//默认查询
		generateMap(QUERY_PARAMS);
		if (StringUtils.isNotBlank(conditions)) {
			QUERY_PARAMS.put(CONDITIONS, conditions);	
		}
		if (StringUtils.isNotBlank(group)) {
			QUERY_PARAMS.put(GROUP, group);
		}
		if (StringUtils.isNotBlank(order)) {
			QUERY_PARAMS.put(ORDER, order);
		}
		if (StringUtils.isNotBlank(limit)) {
			QUERY_PARAMS.put(LIMIT, limit);
		}
		return commonMapper.query(QUERY_PARAMS);
	}
	
	/**
	 * 不分页查询数据
	 */
	public List<Map<String, Object>> query() {
		return query("", "", "", "");
	}
	
	/**
	 * 分页前十
	 */
	public List<Map<String, Object>> queryForTen() {
		return query("", "", "", " limit 0,10 ");
	}
	/**
	 * 分页查询
	 */
	public List<Map<String, Object>> queryForSubsection(int m, int n) {
		return query("", "", "", 
				new StringBuilder(" limit ")
				.append(m).append(",").append(n).toString());
	}
	
	/**
	 * 解析html类数据
	 */
	public abstract Datas<T> dataAnalysisByHtml(Document doc);
	
	/**
	 * 解析html类数据
	 */
	public abstract Datas<T> dataAnalysisByJson(String jsonStr);
	
	
	/**
	 * 获取类对象
	 * @return
	 */
	public abstract  Class<?> getTClass();
	/**
	 * 获取源数据类型
	 * @return
	 */
	public abstract  Type getSourceType();
	
	/**
	 * 组装默认查询条件
	 * 请调用父类常量
	 * @param map
	 */
	public abstract void generateMap(Map<String, Object> map);

	
}
